package edu.pku.sei.act.ctrl.figure;

import org.eclipse.draw2d.AbstractBorder;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.FreeformViewport;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.ScrollPane;
import org.eclipse.draw2d.StackLayout;
import org.eclipse.draw2d.ToolbarLayout;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.widgets.Display;

import edu.pku.sei.gmp.controller.figure.GMPCommonFigure;
import edu.pku.sei.gmp.resource.image.GMPImageProvider;

public class TaskEditAreaFigure extends GMPCommonFigure{

static final Color FILL_COLOR = ColorConstants.white;
	
	public ProcessHeaderFigure headerFigure;
	public ProcessContentFigure contentFigure;
	
	public TaskEditAreaFigure() {
		final ToolbarLayout layout = new ToolbarLayout();
		layout.setSpacing(2);
		setLayoutManager(layout);
		setForegroundColor(ColorConstants.black);
		setBackgroundColor(FILL_COLOR);
		setOpaque(false);
		headerFigure = new ProcessHeaderFigure();
		add(headerFigure);
		add(new CompartmentFigure());
		contentFigure = new ProcessContentFigure();
		add(contentFigure);	
	}
	
	public void changeLineColor(Color color) {
		if (color != null) {
			this.setForegroundColor(color);
			headerFigure.changeBorderColor(color);
		}
	}
	
	protected void paintShadow(Graphics g) {
		g.pushState();
		Rectangle rect = getBounds().getCopy().translate(3, 3);
		g.setClip(rect);
		g.setBackgroundColor(ColorConstants.buttonDarker);
		g.popState();
	}
	
	public IFigure getContentPane() {
		return contentFigure.getContentPane();
	}
	
	
	public ProcessHeaderFigure getHeaderFigure() {
		return headerFigure;
	}

	public void setHeaderFigure(ProcessHeaderFigure headerFigure) {
		this.headerFigure = headerFigure;
	}

	public void setBounds(Rectangle rect) {
		this.headerFigure.setBounds(rect);
		this.contentFigure.setBounds(rect);
		super.setBounds(rect);
	}

	public Label getNameLabel() {
		return this.headerFigure.nameLabel;
	}

	public void setNameLabel(Label nameLabel) {
		this.headerFigure.nameLabel = nameLabel;
	}

	public class ProcessHeaderFigure extends GMPCommonFigure {

		private Label nameLabel;

		public ProcessHeaderFigure() {
			super();
			final ToolbarLayout layout = new ToolbarLayout();
			layout.setSpacing(0);
			setLayoutManager(layout);
			setOpaque(false); // non-transparent figure
			LineBorder border = new LineBorder();
			border.setColor(ColorConstants.gray);
			setBorder(border);
			setForegroundColor(ColorConstants.black);
			setBackgroundColor(FILL_COLOR);
			FontData[] fontdata = { new FontData("Arial", 9, SWT.BOLD) };
			this.nameLabel = new Label("");
			this.nameLabel.setFont(new Font(Display.getCurrent(), fontdata));
			this.nameLabel.setIcon(GMPImageProvider.getImage(GMPImageProvider.FIELD_PACKAGE_IMAGE));
			this.nameLabel.setOpaque(false);
			this.nameLabel.setLabelAlignment(PositionConstants.LEFT);
			this.add(this.nameLabel);
		}

		public void setBounds(Rectangle rectangle) {
			int	headerWidth, headerHeight;
			int nWidth = this.nameLabel.getPreferredSize().width;
			headerWidth = nWidth + 8;
			headerHeight = this.nameLabel.getPreferredSize().height + 4;
			Rectangle.SINGLETON.setLocation(0, 0);
			Rectangle.SINGLETON.setSize(headerWidth, headerHeight);
			super.setBounds(Rectangle.SINGLETON);
		}
		
		public void changeBorderColor(Color color) {
			((LineBorder)getBorder()).setColor(color);
		}
	}
	
	class ProcessContentFigure extends GMPCommonFigure {
		/** pane where the content of the element is draw */
		protected final IFigure pane;

		public ProcessContentFigure() {
			super();
			setLayoutManager(new StackLayout());
			pane = new FreeformLayer();
			pane.setLayoutManager(new FreeformLayout());
			// Add scrollpane
			ScrollPane scrollpane = new ScrollPane();
			scrollpane.setViewport(new FreeformViewport());
			scrollpane.setContents(pane);
			this.add(scrollpane);
			LineBorder border = new LineBorder();
			border.setColor(ColorConstants.gray);
			setBorder(border);
			//setBorder(new LineBorder(0));
			setBackgroundColor(FILL_COLOR);
			setOpaque(false);
		}

		public IFigure getContentPane() {
			return pane;
		}

		@Override
		public void setBounds(Rectangle rect) {
			int fatherHeight = getParent().getBounds().height;
			int fatherWidth  = getParent().getBounds().width;
			int headerY      = headerFigure.getSize().height;
			super.setBounds(new Rectangle(0, headerY-1, fatherWidth, fatherHeight-headerY));
		}
		
		@Override
		protected boolean useLocalCoordinates() {
			return true;
		}
	}
	class CompartmentFigure extends GMPCommonFigure {
		
		protected CompartmentFigureBorder border;

		public CompartmentFigure() {
			ToolbarLayout layout = new ToolbarLayout(ToolbarLayout.VERTICAL);
			layout.setMinorAlignment(ToolbarLayout.ALIGN_TOPLEFT);
			layout.setStretchMinorAxis(true);
			layout.setSpacing(0);
			setLayoutManager(layout);
			setBorder(new CompartmentFigureBorder(ColorConstants.gray, 1, 5, 3, 5, 3));
		}

		public void setBackgroundColor(Color backgroundColor) {
			super.setBackgroundColor(backgroundColor);
			border.setBorder(backgroundColor);
		}
		
	}
	class CompartmentFigureBorder extends AbstractBorder {

		private int lineWidth = 1;
		private Color color;
		protected Insets insets;

		public CompartmentFigureBorder(Color color, int lineWidth, Insets marginInsets) {
			setColor(color);
			setLineWidth(lineWidth);
			this.insets = marginInsets;
			insets.top += lineWidth; 
		}
		
		// to adapt the color of the border.
		public void setBorder(Color color){
			this.setColor(color);
		}

		// Constructs a LineBorder with the specified color and of the specified width. 
		public CompartmentFigureBorder(Color color, int lineWidth, int allMargin) {
			this(color, lineWidth, new Insets(allMargin) );
		}
		// Constructs a LineBorder with the specified color and of the specified width.
		public CompartmentFigureBorder(Color color, int lineWidth, int t, int l, int b, int r) {
			this(color, lineWidth, new Insets(t, l, b, r) );
		}
		
		//Constructs a LineBorder with the specified color and a width of 1 pixel.
		public CompartmentFigureBorder(Color color) {
			this(color, 1, 1);
		}

		// Constructs a black LineBorder with the specified width.
		public CompartmentFigureBorder(int width) {
			this(null, width, width);
		}

		// Constructs a default black LineBorder with a width of one pixel.
		public CompartmentFigureBorder() { }

		public Color getColor() {
			return color;
		}

		/**
		 * Returns the space used by the border for the figure provided as input. In this border
		 * all sides always have equal width.
		 */
		public Insets getInsets(IFigure figure) {
			return insets;
		}

		
		public int getLineWidth() {
			return lineWidth;
		}

		@Override
		public boolean isOpaque() {
			return true;
		}
		
		public void paint(IFigure figure, Graphics graphics, Insets insets) {
			graphics.pushState();
			Rectangle bounds = figure.getBounds();
			graphics.setLineWidth(getLineWidth());
			if (getColor() != null) {
				graphics.setForegroundColor(getColor());
			}
			graphics.drawLine(bounds.getTopLeft(), bounds.getTopRight());
			graphics.popState();
		}

		public void setColor(Color color) {
			this.color = color;
		}

		public void setLineWidth(int width) {
			this.lineWidth = width;
		}

	}
	protected boolean useLocalCoordinates() {
		return true;
	}
}

